Date field
canonInput that parses typed dates and opens the calendar panel.
Used in 30 files · 21 areas · 56× — components/accounting, components/callwrapup, components/clen-tymu, components/dialog, components/kpi, components/mail …
The single-date input of the design system. React <DateField> (packages/ui/src/components/DateField.tsx) emits .dp-field + .dp-input + .dp-open from the engine apps/web/src/ds/date-picker.css. It replaces every native <input type="date"> in the app (canon since 21 Aug 2026): the date can be typed ("26.8.", "dnes", "pá", "+7", "za 14 dní") and the calendar is the second way in, not the only one.
When to use
- Any field that holds exactly one date: task due date, meeting date, invoice date, date of birth.
- "Termín" is always a single date — the second date of an event is a consequence handled by Date-time range, never a second Date field next to it.
- Inline editing in the record rail (
autoFocusafter the row is activated). - Dates that usually lie ahead (due dates, deadlines): pass
futureBiasso "1.9." typed in December means next year.
When not to use
- A from–to span in a filter or report — use Date range.
- Date plus time of an event — use Date-time range.
- Time only — use Time field.
- A picker embedded in a menu or rail without an input — use Calendar directly inside the host menu.
- Native
<input type="date">,type="month"ortype="datetime-local"anywhere in the app; tests (rail-date-field.test.tsx,advance-settle-month.test.tsx) assert their absence.
Anatomy
- Wrapper
.dp-fieldset: column, gap--sp-1; holds the field, the optional echo line and the portal anchor. - Field
.dp-field: flex, height 32px, padding0 var(--sp-2) 0 var(--sp-3), background--surface-100, 1px border--border-strong, radius--radius-sm; flat at rest (no shadow). - Input
.dp-input: width 168px,400 13px var(--font-sans), colour--ink-900, placeholder--fg-muted; shows the value throughformatDate(year only when needed). - Calendar trigger
.dp-open: 24×24 quiet button, icon--ico-sm,aria-haspopup="dialog", opens Picker panel with Calendar (singleDatePresets: Dnes / Zítra / Příští týden) and a.dp-foot"Vymazat" once a value exists. - Echo
.dp-echo: live interpretation of typed text under the field ("→ pátek 26. 8.");.badturns--criticalwith the parser note. Exists only while typing; collapses when empty. - States:
:focus-withinaccent border + 3pxcolor-mix(--accent 16%)ring;.err(errorprop or unparsable commit)--criticalborder and ring;.disabledbackground--surface-75, border--border, muted text. - Value contract: ISO
YYYY-MM-DDornullin both directions;min/maxlimit both the calendar and the typed value — a typed date outside the range is not committed, the echo shows „Nejdříve …" / „Nejpozději …" and the field turns.err(30 Sep 2026).todayanchors the relative grammar for tests.
Best practices
Do
- One
<DateField>for "Termín"; let the user type ("zítra", "+7") and keep the calendar as the alternative. - Wrap it in
<Field label="Termín">and put the validation message inField.error, not in the placeholder. - Set
futureBiason due dates andmin/maxwhere the business rule really exists (booking window). - Keep the default width: 168px input plus trigger — width is content, the field is not stretched to the form column.
Don’t
- Two Date fields side by side for an event start/end — Date-time range owns the second date.
- Opening the calendar on focus — six dated fields in a form must remain tabbable; only the icon or ↓ opens it.
- A custom label inside the field ("Datum:") or a hard-coded format like
${d.getDate()}. ${d.getMonth()+1}.. - Showing dates with
tabular-numsor with a year when the date is in the current year.
Content
- Display format comes from
formatDate(packages/ui/src/lib/date-core.ts): current year "26. 8.", another year of this century "14. 11. 27", another century "11. 2. 1988"; non-breaking spaces incs-CZ. - Placeholder default "Doplnit…"; keep it as a verb hint, never an example format.
- Echo text is generated: "→ pátek 26. 8." on success; parser notes on failure ("Nerozumím — zkus 26.8. nebo „za 14 dní“", "Který měsíc? …", "únor 2027 má 28 dní").
ariaLabeldefault "Datum"; the visible label lives in<Field label>in sentence case.- Never send
formatDateoutput to the API — the wire value is ISO.
Related
- calendar — the month grid the field opens.
- picker-panel — the floating layer that hosts it.
- time-field — companion for the time part.
- date-range, date-time-range — spans built from this field.
- Legacy card
legacy/dates.html: year convention still valid; its implementation path (apps/web/src/i18n/date-core.ts) and the mention of<input type="date">are superseded — the source ispackages/ui/src/lib/date-core.tsand native date inputs are gone.
Source: docs/date-time/date-field.usage.md · GitLab